package utils

import "fmt"

type chanTaskItem struct {
	fn   func(args ...interface{})
	args []interface{}
}

type ChanTask struct {
	Terminated int8
	taskChan   chan *chanTaskItem
}

func NewChanTask(maxCache int) *ChanTask {
	rval := &ChanTask{
		taskChan: make(chan *chanTaskItem, maxCache),
	}
	rval.start()
	return rval
}

func (this *ChanTask) innerExec(itm *chanTaskItem) {
	if GoFunCatchException {
		defer PanicHandler()
	}
	itm.fn(itm.args...)
}

func (this *ChanTask) innerWork() {
	if GoFunCatchException {
		defer PanicHandler()
	}
break_for:
	for {
		select {
		case itm := <-this.taskChan:
			if itm == nil {
				break break_for
			}
			if this.Terminated == 0 {
				this.innerExec(itm)
			}
		}
	}
}

func (this *ChanTask) start() {
	go this.innerWork()
}

func (this *ChanTask) Stop() {
	this.Terminated = 1
	this.taskChan <- nil
}

func (this *ChanTask) StatusString() string {
	return fmt.Sprintf("size:%d", len(this.taskChan))
}

func (this *ChanTask) PushTask(fn func(args ...interface{}), args ...interface{}) {
	itm := &chanTaskItem{fn: fn, args: args}
	this.taskChan <- itm
}
